<?php
/**
 * CK 开发框架
 * User: Clake
 * Date: 15/6/13
 * Time: 02:06
 */

namespace CK\Core;

use CK\Util\IO\Directory;
use CK\Util\IO\File;

/**
 * Class Loader
 * 自动加载类
 * @package CK\Core
 */
class Loader extends Base{

    private static $_instance;

    private $_conf = [
        'map'=>[],
        'include_path'=>APP_LIB_PATH,
        'libs'=>[],
        'file_ext'=>'.php'
    ];
    /**
     * @var array 类映射数组
     */
    private $_class_map = [];

    /**
     * @var string 默认加载路径
     */
    private $_include_path = '';

    /**
     * @var string 加载文件扩展名
     */
    private $_file_ext = '';

    /**
     * @var array 第三方加路径
     */
    private $_libs = [];

    public static function inst($conf=null) {
        if (!isset(self::$_instance)) {
            self::$_instance = new self($conf);
        }

        return self::$_instance;
    }

    public function __construct($conf) {
        if (is_array($conf)) {
            $this->_conf = array_merge($this->_conf,$conf);
        }

        $conf = C('loader');
        if (is_array($conf)) {
            $this->_conf = array_merge($this->_conf,$conf);
        }

        $this->_class_map = $this->_conf['map'];

        $this->_include_path = $this->_conf['include_path'];

        $this->_file_ext = $this->_conf['file_ext'];

        $this->_libs = $this->_conf['libs'];
    }

    /**
     * 添加类映射
     * @param array $class_map
     */
    public function addClassMap(array $class_map) {
        if (is_assoc($class_map)) {
            $this->_class_map = array_merge($this->_class_map,$class_map);
        }
    }

    /**
     * 自动加载方法
     */
    public function load($class) {
        if ($file = $this->findFile($class)) {
            IncludeFile($file);
            return true;
        }
    }

    /**
     * 查找类文件
     *
     * @param $class
     *
     * @return bool|null|string
     */
    public function findFile($class) {

        //去除文件头斜线
        if ('\\' == $class[0]) {
            $class = substr($class, 1);
        }

        //如果已经有映射直接返回文件
        if (isset($this->_class_map[$class])) {
            return $this->_class_map[$class];
        }

        $file = $this->_include_path.str_replace('\\','/',$class).$this->_file_ext;

        //检查类文件是否存在
        if (!File::Exists($file)) {
            $file = $this->findOtherLib($class);
        }

        if ($file === null) {
            //如果不存在类文件,存保状态
            return $this->_class_map[$class] = false;
        }

        return $file;
    }

    //查找第三方库
    public function findOtherLib($class) {
        $arr = explode('\\',$class);
        if (isset($this->_libs[$arr[0]])) {
            $path = $this->_libs[$arr[0]].str_replace('\\','/',$class).$this->_file_ext;
            return $path;
        }
        return null;
    }

    /**
     * 注册自动加载方法
     * @param bool $prepend
     */
    public function register($prepend = false) {
        spl_autoload_register([$this, 'load'], true, $prepend);
    }

    /**
     * 注消自动加载方法
     */
    public function unregister() {
        spl_autoload_unregister([$this, 'load']);
    }
}

/**
 * 加载文件作用域孤立
 * @param $file
 */
function IncludeFile($file) {
    include $file;
}